#include "losu.h"
#include "losu_bytecode.h"
#include "losu_dump.h"
#include "losu_gc.h"
#include "losu_mem.h"
#include "losu_object.h"
#include "losu_syntax.h"
#include "losu_vm.h"

#include "vector.h"
#include "../xkit.h"
#include "collections.h"

static inline int32_t returnObj(losu_vm_t vm, losu_object_t o) {
    stack_push(vm, *o);
    return 1;
}

/** losu-capi (self) -> self
 * @brief: "constructor of class: THISxkit_MODULEcollections_CLASSVector"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_constructor(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    (void)argc;
    VectorHeader *h = VectorInit(vm);
    obj_unitsetstr(vm, *argv, "__cptr__", obj_newptr(vm, (void*)h));
    return returnObj(vm, argv);
}

/** losu-capi (size: number) -> self
 * @brief: ""
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCreserve(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    if (argc < 2) {
        __error_TooFewArguments(vm);
        return 0;
    }
    VectorHeader *h = VectorInit(vm);
    size_t size = obj_getnum(vm, argv+1);
    VectorReserve(vm, h, size);
    return returnObj(vm, argv);
}

/** losu-capi () -> 
 * @brief: ""
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNC__del__(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    (void)argc;
    VectorHeader *h = getCPointer(vm, argv);
    VectorFree(vm, h);
    obj_unitsetstr(vm, *argv, "__cptr__", obj_newfalse(vm));
    gc_collect(vm);
    return 0;
}


/** losu-capi () -> self
 * @brief: "清空列表"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCclear(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    (void)argc;
    VectorHeader *h = getCPointer(vm, argv);
    VectorClear(vm, h);
    return returnObj(vm, argv);
}


/** losu-capi () -> number
 * @brief: "返回列表的长度"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCsize(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    (void)argc;
    VectorHeader *h = getCPointer(vm, argv);
    return arg_returnNum(vm, h->curIndex);
}


/** losu-capi (self, a: number, b: number) -> self
 * @brief: "交换两个位置的数据"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCswap(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    (void)argc;
    if (argc < 3) {
        __error_TooFewArguments(vm);
        return 0;
    }
    VectorHeader *h = getCPointer(vm, argv);
    size_t a = obj_getnum(vm, argv+1);
    size_t b = obj_getnum(vm, argv+2);
    if (a >= h->curIndex || b >= h->curIndex) {
        __error_OutOfIndex(vm);
    } else {
        losu_object temp = h->val[a];
        h->val[a] = h->val[b];
        h->val[b] = temp;
    }
    return returnObj(vm, argv);
}

/** losu-capi (...: List) -> self
 * @brief: "将对应的List添加到列表末尾"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCextend(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    if (argc < 2) {
        __error_TooFewArguments(vm);
        return 0;
    }
    VectorHeader *a = getCPointer(vm, argv);
    for (size_t i = 1; i < (size_t)argc; i ++) {
        VectorHeader *b = getCPointer(vm, argv+1);
        VectorExtend(vm, a, b);
    }
    return returnObj(vm, argv);
}


/** losu-capi (...: Any) -> self
 * @brief: "将item添加到列表末尾"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCappend(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    if (argc < 2) {
        __error_TooFewArguments(vm);
        return 0;
    }
    VectorHeader *h = getCPointer(vm, argv);
    for (size_t i = 1; i < (size_t)argc; i ++) {
        losu_object_t o = argv + i;
        VectorAppend(vm, h, o);
    }
    return returnObj(vm, argv);
}


/** losu-capi (...: number) -> ...: item
 * @brief: "按index返回列表的元素,越界时引发错误"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCget(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    if (argc < 2) {
        __error_TooFewArguments(vm);
        return 0;
    }
    VectorHeader *h = getCPointer(vm, argv);
    losu_object o;
    size_t i = 1;

    for (; i < (size_t)argc; i ++) {
        size_t index = obj_getnum(vm, argv+i);
        if (!VectorGet(vm, h, index, &o)) {
            __error_OutOfIndex(vm);
        }
        stack_push(vm, o);
    }

    return i - 1;
}


/** losu-capi (self, index: number, item: Any) -> self
 * @brief: "向item插入列表的index位置"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCinsert(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    if (argc < 3) {
        __error_TooFewArguments(vm);
        return 0;
    }
    VectorHeader *h = getCPointer(vm, argv);
    size_t index = obj_getnum(vm, argv+1);
    losu_object_t item = argv + 2;
    VecotrInsert(vm, h, index, item);
    return returnObj(vm, argv);
}


/** losu-capi (self, index: number, item: Any) -> self
 * @brief: "将index处的对象替换为item,,越界时引发错误"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCset(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    if (argc < 3) {
        __error_TooFewArguments(vm);
        return 0;
    }
    VectorHeader *h = getCPointer(vm, argv);
    size_t index = obj_getnum(vm, argv+1);
    losu_object_t item = argv + 2;
    VecotrReplace(vm, h, index, item);
    return returnObj(vm, argv);
}


/** losu-capi (self, index: number) -> self
 * @brief: "弹出列表对应的元素，默认为最后一个,越界时引发错误"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCpop(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    VectorHeader *h = getCPointer(vm, argv);
    size_t index;
    if (argc < 2) {
        if (h->curIndex == 0) {
            __error_OutOfIndex(vm);
            return 0;
        }
        index = h->curIndex - 1;
    } else {
        index = obj_getnum(vm, argv+1);
    }

    losu_object target;
    VectorPop(vm, h, index, &target);
    return returnObj(vm, &target);
}

/** losu-capi (self) -> self
 * @brief: "将元素倒置"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCreverse(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    (void)argc;
    VectorHeader *h = getCPointer(vm, argv);
    losu_object_t front, tear;
    if (h->curIndex > 1) {
        front = h->val;
        tear = h->val + h->curIndex - 1;
        do {
            losu_object temp = *front;
            *front = *tear;
            *tear = temp;
            front ++;
            tear --;
        } while (front < tear);
    }
    return returnObj(vm, argv);
}

/** losu-capi (self) -> self
 * @brief: "裁剪到实际大小"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCtrim(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    (void)argc;
    VectorHeader *h = getCPointer(vm, argv);
    VectorTrim(vm, h);
    return returnObj(vm, argv);
}

/** losu-capi (self, start: number, end: number) -> 
 * @brief: "切片，范围为[start, end)"
 */
int32_t THISxkit_MODULEcollections_CLASSVector_FUNCslice(losu_vm_t vm, int32_t argc, losu_object argv[]) {
    if (argc < 3) {
        __error_TooFewArguments(vm);
        return 0;
    }
    VectorHeader *h = getCPointer(vm, argv);
    losu_object_t reflect = obj_unitindexstr(vm, *argv, "__reflect__");
    losu_object out = obj_newunit(vm, obj_unittype_object);

    size_t start = obj_getnum(vm, argv+1);
    size_t end = obj_getnum(vm, argv+2);

    VectorHeader *outPtr = VectorSlice(vm, h, start, end);
    losu_hash_node_t node = obj_unititer(vm, *reflect, NULL);

    while (node) {
        obj_unitset(vm, out, obj_unititerkey(vm, node), obj_unititerval(vm, node));
        node = obj_unititer(vm, *reflect, node);
    }

    obj_unitsetstr(vm, out, "__init__", obj_newfalse(vm));
    obj_unitsetstr(vm, out, "__cptr__", obj_newptr(vm, outPtr));

    stack_push(vm, out);
    return 1;
}
